#include "CassiopeiaLibrary.h"
#include "Settings.h"
#include "KeyLock3.h"

///Copyright (c) 2009-2010 T. Klepzig 

//Enable Visual Styles
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")


#define TrayMenu_KeyLockActive						8
#define TrayMenu_KeyLockLockAtUnplug				9
#define TrayMenu_Separator2							10
#define TrayMenu_KeyLockLock						11
#define TrayMenu_Separator3							12
#define TrayMenu_KeyLockSetPrimaryDevice			13
#define TrayMenu_KeyLockClearPrimaryDevice			14
#define TrayMenu_Separator4							15
#define TrayMenu_KeyLockSetSecondaryDevice			16
#define TrayMenu_KeyLockClearSecondaryDevice		17
#define TrayMenu_Separator5							18
#define TrayMenu_Close								19


HMENU trayMenu = 0;
KeyLock3* keyLock = 0;
UINT WM_TASKBARCREATED = 0;
NOTIFYICONDATA notifyIconData = {0};
bool activeStateChangedByUser = true;

void KeyLockActiveChanged(CassiopeiaComponent* sender, bool active)
{
	if (activeStateChangedByUser)
	{
		Settings::GetData()->KeyLockData.Active = active;
		Settings::Save();
	}

	CheckMenuItem(trayMenu,TrayMenu_KeyLockActive,active?MF_CHECKED:MF_UNCHECKED);
	EnableMenuItem(trayMenu,TrayMenu_KeyLockLock,active?MF_ENABLED:MF_DISABLED);
}

LRESULT CALLBACK WndProc(LPVOID sender, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{	
	if (uMsg == WM_TASKBARCREATED)
		Shell_NotifyIcon(NIM_ADD, &notifyIconData);

	switch (uMsg)
	{
	case WM_APP + 1:
		{
			switch(LOWORD(lParam))
			{
			case WM_RBUTTONDOWN:
			case WM_CONTEXTMENU:
				{
					POINT cursorPos = Utilities::GetCursorPosition();
					SetForegroundWindow(hWnd);
					TrackPopupMenu(trayMenu, TPM_VERPOSANIMATION | TPM_LEFTBUTTON, cursorPos.x, cursorPos.y, 0, hWnd, 0);
					PostMessage(hWnd, WM_NULL, 0, 0);
					break;
				}
			case WM_LBUTTONDBLCLK:
				{
					PostQuitMessage(0);
					break;
				}
			}

			break;
		}
	case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
			case TrayMenu_KeyLockActive:
				{
					keyLock->ToggleActiveState();
					break;
				}
			case TrayMenu_KeyLockLockAtUnplug:
				{
					keyLock->SetLockAtUnplug(!keyLock->GetLockAtUnplug());
					CheckMenuItem(trayMenu,TrayMenu_KeyLockLockAtUnplug,keyLock->GetLockAtUnplug()?MF_CHECKED:MF_UNCHECKED);

					break;
				}
			case TrayMenu_KeyLockLock:
				{
					keyLock->Lock();
					break;
				}
			case TrayMenu_KeyLockSetPrimaryDevice:
				{
					keyLock->SetPrimaryDevice();
					break;
				}
			case TrayMenu_KeyLockClearPrimaryDevice:
				{
					keyLock->ClearPrimaryDevice();
					break;
				}
			case TrayMenu_KeyLockSetSecondaryDevice:
				{
					keyLock->SetSecondaryDevice();
					break;
				}
			case TrayMenu_KeyLockClearSecondaryDevice:
				{
					keyLock->ClearSecondaryDevice();
					break;
				}
			case TrayMenu_Close:
				{
					PostQuitMessage(0);
					break;
				}
			}
			break;
		}
	case WM_DESTROY:	
		{
			PostQuitMessage(0);
			break;
		}
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine,
	int nShowCmd)
{
	WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));

	#pragma region Allow only one instance of KeyLock

	HANDLE hMutex = CreateMutex(0,FALSE,TEXT("{D59B2A4F-716B-460A-BF4E-2FE9E4EA4D51}"));

	if (hMutex && GetLastError() == ERROR_ALREADY_EXISTS)
	{
		ReleaseMutex(hMutex);
		return 0;
	}

	ReleaseMutex(hMutex);

	#pragma endregion	

	#pragma region initialize gdi+

	ULONG_PTR gdiplusToken;  
	GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, 0);
	
	#pragma endregion	

	#pragma region manipulate working directory, so that it is always the same directory as the executable

	TCHAR path[_MAX_PATH]={0};
	TCHAR drive[_MAX_DRIVE]={0};
	TCHAR dir[_MAX_DIR]={0};
	TCHAR fileName[_MAX_FNAME]={0};
	TCHAR ext[_MAX_EXT]={0};

	GetModuleFileName(0, path, _MAX_PATH);

	_tsplitpath(path,drive,dir,fileName,ext);
	_tmakepath(path,drive, dir, 0,0);

	SetCurrentDirectory(path);

	#pragma endregion


	Settings::GetData()->KeyLockData.Active = false;
	Settings::GetData()->KeyLockData.LockAtUnplug = false;
	Settings::GetData()->KeyLockData.Locked = false;
	Settings::GetData()->KeyLockData.PrimarySerialNumber = 0;
	Settings::GetData()->KeyLockData.SecondarySerialNumber = 0;

	Settings::Load();

	Window *hiddenWindow = new Window();
	hiddenWindow->Create(hInstance, TEXT("KeyLockMainWindow"), WndProc);

	//Icon Data: Cassiopeia_Green -> Colorize: (H,S,L) - (0, 85, 0)
	notifyIconData.cbSize = sizeof(NOTIFYICONDATA);
	notifyIconData.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
	notifyIconData.uID = 43;
	notifyIconData.uVersion = NOTIFYICON_VERSION_4;
	notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	_tcscpy(notifyIconData.szTip, TEXT("Cassiopeia - KeyLock"));
	notifyIconData.hWnd = hiddenWindow->GetHWnd();
	notifyIconData.uCallbackMessage = WM_APP + 1;
	Shell_NotifyIcon(NIM_ADD, &notifyIconData);

	trayMenu = CreatePopupMenu();
	
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockActive, TEXT("Active"));
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockLockAtUnplug, TEXT("Lock At Unplug"));
	AppendMenu(trayMenu, MF_SEPARATOR, TrayMenu_Separator2, 0);
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockLock, TEXT("Lock\tWin+K"));
	AppendMenu(trayMenu, MF_SEPARATOR, TrayMenu_Separator3, 0);
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockSetPrimaryDevice, TEXT("Set Primary Device..."));
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockClearPrimaryDevice, TEXT("Clear Primary Device"));
	AppendMenu(trayMenu, MF_SEPARATOR, TrayMenu_Separator4, 0);
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockSetSecondaryDevice, TEXT("Set Secondary Device..."));
	AppendMenu(trayMenu, MF_STRING, TrayMenu_KeyLockClearSecondaryDevice, TEXT("Clear Secondary Device"));
	AppendMenu(trayMenu, MF_SEPARATOR, TrayMenu_Separator5, 0);
	AppendMenu(trayMenu, MF_STRING, TrayMenu_Close, TEXT("Exit"));
	SetMenuDefaultItem(trayMenu, TrayMenu_Close, 0);


	keyLock = new KeyLock3(hInstance);
	keyLock->ActiveChanged(KeyLockActiveChanged);
	
	if (Settings::GetData()->KeyLockData.Active)
		keyLock->Activate();
	else
		EnableMenuItem(trayMenu, TrayMenu_KeyLockLock, MF_DISABLED);

	if (keyLock->GetLockAtUnplug())
		CheckMenuItem(trayMenu, TrayMenu_KeyLockLockAtUnplug, MF_CHECKED);

	MSG msg;
	while(GetMessage(&msg,0,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	Settings::GetData()->KeyLockData.Active = keyLock->IsActive();
	Settings::Save();

	activeStateChangedByUser = false;

	delete hiddenWindow;
	delete keyLock;

	DestroyMenu(trayMenu);
	Shell_NotifyIcon(NIM_DELETE, &notifyIconData);

	#pragma region shutdown gdi+

	GdiplusShutdown(gdiplusToken);

	#pragma endregion	
	
	return msg.wParam;
}
